import os, sys, pickle, datetime
import pygame
from pygame.locals import *
try:
    import android
except ImportError:
    android = None
if android:
    import android.mixer
import codecs

if android:
    sys.path.insert(0, "..")
from pgu import gui

from sounds import s
from display import d
d.initialize()
s.initialize()

if android:
    savedir = '/mnt/sdcard/Android/data/demo.demo/files/'
    logdir = savedir
    if not os.path.exists(savedir):
        os.makedirs(savedir)
    # change demo.demo to the package name if this changes
    d.logfile = codecs.open(logdir + "log_" + datetime.datetime.now().strftime("%Y-%b-%d_%H-%M-%S") + ".txt","w",encoding='utf-8')
else:
    savedir = './save/'
    logdir = './log/'
    d.logfile = open(logdir + "log_" + datetime.datetime.now().strftime("%Y-%b-%d_%H-%M-%S") + ".txt","w")

from game import *
from dungeon import adventures # map from string to function making'scenario'
from town import parties # map from string to 'charsheets'
    
if os.path.exists(savedir + "/save.pk"):
    try:
        file = open(savedir + "/save.pk","rb")
        unpack = pickle.load(file)
        p.__dict__.update(unpack[0].__dict__)
        w.__dict__.update(unpack[1].__dict__)
        e.__dict__.update(unpack[2].__dict__)
        w.now = pygame.time.get_ticks()
        w.since_last_process = w.now
        file.close()
        d.just_loaded = True
        d.just_new = False
        d.log('Loaded game')
    except:
        d.just_loaded = False
        d.just_new = True
        d.log('New game 1')
else:
    d.just_loaded = False
    d.just_new = True
    d.log('New game 2')

def end():
    file = open(savedir + "/save.pk","wb")
    someone_alive = False
    for c in p.chars:
        if c.alive and not c.about_to_die:
            someone_alive = True
    if (someone_alive and not w.dungeon_won and not w.party_fleeing):
        d.log('Saving')
        pickle.dump([p,w,e], file, 2)
        file.flush()
    else:
        d.log('No save')
    file.close()
    d.log('Exiting')
    d.logfile.flush()
    d.logfile.close()
    sys.exit()

def main():
    # go for it
    w.now = pygame.time.get_ticks()
    w.since_last_process = w.now
    
    # main loop
    while 1:
        if android:
            if android.check_pause():
                w.now = pygame.time.get_ticks()
                android.wait_for_resume()
                w.now = pygame.time.get_ticks()
                w.since_last_process = w.now
        # just started?
        if d.just_new:
            w.resetting = True
            charsheets = parties[d.chooser_dialog(w,'Choose a party',parties.keys())]
            scenario = adventures[d.chooser_dialog(w,'Choose an adventure',adventures.keys())]
            w.resetting = False
            p.reset(charsheets)
            w.reset(scenario)
            e.reset()
            d.just_new = False
            for c in p.chars:
                c.slide_from = POS_DOWN
                c.slide_to = c.pos
                c.slide_start = w.elapsed_since_beginning
                c.slide_finish = w.elapsed_since_beginning + 0.3
        elif d.just_loaded:
            d.print_message('Resume battle!',None,COL_LIGHT)
            d.just_loaded = False
        # update world occasionally
        new_time = pygame.time.get_ticks()
        elapsed = (new_time - w.now)/1000.0
        if elapsed >= 0.025:
            w.now = new_time
            w.process()
        # print messages and sounds
        if w.elapsed_since_beginning > w.silence_until:        
            for sound in d.sound_queue:
                s.play(sound)
            d.sound_queue = []
        if d.mode==M_NORMAL:
            for message in d.message_queue:
                d.print_message(message[0],message[1],message[2])
            d.message_queue = []
        # redraw screen
        d.redraw(p,e,w)
        # is the game over?
        if d.quit_after_pause is True or d.quit_now is True:
            file = open(savedir + "/save.pk","w")
            file.close()
            d.logfile.close()
            if d.quit_after_pause is True:
                now = w.now
                while pygame.time.get_ticks() <= now + 3000:
                    new_time = pygame.time.get_ticks()
                    elapsed = (new_time - w.now)/1000.0
                    if elapsed >= 0.025:
                        w.now = new_time
                        w.process()
                    d.redraw(p,e,w)
            sys.exit()
        # maybe give up on the current action, if it seems to be taking a long time
        if (d.mode==M_CHOOSE_FRIENDLY_TARGET or d.mode==M_CHOOSE_ENEMY_TARGET) and (w.now-w.asked_for_target)/1000.0 >= 5:
            d.mode = M_NORMAL
            if w.elapsed_since_beginning > w.silence_until:
                s.play(S_CANCEL)
            d.print_message('Action cancelled',None,COL_LIGHT)
        if d.mode==M_CHOOSE_ACTION:
            if (w.now-w.asked_for_action)/1000.0 >= 5:
                d.mode = M_NORMAL
                if w.elapsed_since_beginning > w.silence_until:
                    s.play(S_CANCEL)
                d.print_message('Action cancelled',None,COL_LIGHT)
            if len(d.action_choices)==0:
                d.mode = M_NORMAL
        # seek input and react
        a = d.get_click()
        if a is None:
            if d.mode==M_DRAGGING and d.button_still_down==True and d.started_dragging_at + 0.7 <= w.elapsed_since_beginning:
                # we have done a long click on a player button and not unclicked yet
                for pos in [POS_C_FRONT_1, POS_C_FRONT_2, POS_C_FRONT_3, POS_C_BACK_1, POS_C_BACK_2, POS_C_BACK_3]:
                    mouse = d.get_mouse_pos()
                    if mouse is not None and d.pos_to_image_rect[pos].collidepoint(mouse):
                        if pos==d.actor.pos:
                            d.log('')
                            chardump = d.actor.get_chardump()
                            for line in chardump:
                                d.log(line)
                            d.log('')
                            d.container_info_dialog(w,d.actor.name,d.actor.image,d.actor.get_container_chardump())
                            d.actor = None
                            if w.elapsed_since_beginning > w.silence_until:
                                s.play(S_KEY)
                            d.mode = M_NORMAL
                            d.button_still_down = False
                            d.redraw(p,e,w)
            elif d.mode==M_DRAGGING and d.button_still_down==True and pygame.mouse.get_pressed()[0]==False:
                d.mode = M_NORMAL
                d.actor = None
                d.button_still_down = False
            else:
                pass
        elif a==-1:
            # input is to request save and close
            end()
        elif d.pause_rect.collidepoint(a) and d.button_still_down is False:
            # input is to hit pause
            w.now = pygame.time.get_ticks()
            w.process()
            if w.elapsed_since_beginning > w.silence_until:
                s.play(S_KEY)
            d.grey_out = True
            while d.button_still_down is False:
                if android:
                    if android.check_pause():
                        w.now = pygame.time.get_ticks()
                        android.wait_for_resume()
                        w.now = pygame.time.get_ticks()
                        w.since_last_process = w.now
                click = d.get_click()
                if click is None:
                    pass
                elif click==-1:
                    d.logfile.close()
                    raise SystemExit
                else:
                    continue
                d.redraw(p,e,w)
            while d.button_still_down is True:
                if android:
                    if android.check_pause():
                        w.now = pygame.time.get_ticks()
                        android.wait_for_resume()
                        w.now = pygame.time.get_ticks()
                        w.since_last_process = w.now
                click = d.get_click()
                if click is None:
                    pass
                elif click==-1:
                    d.logfile.close()
                    raise SystemExit
                else:
                    continue
                d.redraw(p,e,w)
            d.grey_out = False
            w.now = pygame.time.get_ticks()
            w.since_last_process = w.now
            if w.elapsed_since_beginning > w.silence_until:
                s.play(S_KEY)
        elif d.quit_rect.collidepoint(a):
            # input is to hit save and quit
            if d.button_still_down is True:
                end()
            elif d.mode==M_DRAGGING and d.button_still_down==False:
                # player has stopped either clicking or dragging
                if w.elapsed_since_beginning > w.silence_until:
                    s.play(S_KEY)
                d.mode = M_NORMAL
        elif d.restart_rect.collidepoint(a):
            # input is to hit retry
            if d.button_still_down is True:
                #w.resetting = True
                #charsheets = parties[d.chooser_dialog(w,'Choose a party',parties.keys())]
                #scenario = adventures[d.chooser_dialog(w,'Choose an adventure',adventures.keys())]
                #w.resetting = False
                #p.reset(charsheets)
                #w.reset(scenario)
                #e.reset()
                d.scrub()
                d.just_new = True
                d.log('Restarting')
                file = open(savedir + "/save.pk","w")
                file.close()
            elif d.mode==M_DRAGGING and d.button_still_down==False:
                # player has stopped either clicking or dragging
                if w.elapsed_since_beginning > w.silence_until:
                    s.play(S_KEY)
                d.mode = M_NORMAL
        elif d.mode==M_NORMAL:
            if d.flee_rect.collidepoint(a):
                # input is to flee
                if not d.button_still_down:
                    if w.can_flee and not w.party_fleeing:
                        if w.elapsed_since_beginning > w.silence_until:
                            s.play(S_KEY)
                        w.party_fleeing = True
                        d.print_message('Time to fight another day...',None,COL_LIGHT)
                    elif not w.can_flee:
                        if w.elapsed_since_beginning > w.silence_until:
                            s.play(S_CANCEL)
                        d.print_message('There is no escape!',None,COL_LIGHT)
            else:
                # input _may_ be to hit a character button
                if not d.button_still_down:
                    if w.elapsed_since_beginning > w.silence_until:
                        s.play(S_KEY)
                for c in p.chars:
                    if c.alive and not c.about_to_die:
                        if d.pos_to_image_rect[c.pos].collidepoint(a):
                            if c.can_act():
                                d.actor = c
                                if d.button_still_down:
                                    d.mode = M_DRAGGING
                                    d.started_dragging_at = w.elapsed_since_beginning
                                else:
                                    d.mode = M_CHOOSE_ACTION
                                    #d.simple_dialog(w)
                                    d.action_choices = []
                                    w.asked_for_action = w.now
                            elif c.has_status_effect(EF_SLEEP) and not d.button_still_down:
                                c.status_effects[EF_SLEEP].level = c.status_effects[EF_SLEEP].level-1
                                if c.status_effects[EF_SLEEP].level<=0:
                                    c.status_effects[EF_SLEEP].lasts_until = 0
                    continue
                if not d.button_still_down:
                    for m in e.mobs:
                        if m.alive and m.pos is not None:
                            if d.pos_to_image_rect[m.pos].collidepoint(a):        
                                d.log('')
                                chardump = m.get_chardump()
                                for line in chardump:
                                    d.log(line)
                                d.log('')
                                d.container_info_dialog(w,m.name,m.image,m.get_container_chardump())
        elif d.mode==M_DRAGGING and d.button_still_down==False:
            # player has stopped either clicking or dragging
            if w.elapsed_since_beginning > w.silence_until:
                s.play(S_KEY)
            d.mode = M_NORMAL
            for pos in [POS_C_FRONT_1, POS_C_FRONT_2, POS_C_FRONT_3, POS_C_BACK_1, POS_C_BACK_2, POS_C_BACK_3]:
                if d.pos_to_image_rect[pos].collidepoint(a):
                    if pos<>d.actor.pos:
                        # it was dragging
                        p.move_character_to(d.actor,pos)
                        d.actor = None
                continue
            if d.actor is not None:
                # it may have been clicking
                dragged_actor = d.actor
                d.actor = None
                for c in p.chars:
                    if c.alive and not c.about_to_die:
                        if d.pos_to_image_rect[c.pos].collidepoint(a):
                            if c.can_act() and c==dragged_actor:
                                d.actor = c
                                d.mode = M_CHOOSE_ACTION
                                #d.simple_dialog(w)
                                d.action_choices = []
                                w.asked_for_action = w.now
                    continue
        elif d.mode==M_CHOOSE_ACTION and d.button_still_down==False:
            # choose an action from the options provided
            found_action = False
            for count in range(0,len(d.action_choices)):
                if d.action_rects[count].collidepoint(a):
                    found_action = True
                    action = d.action_choices[count]
                    if d.action_choices[count].ok():
                        # an action has been chosen
                        d.target = None
                        d.action = action
                        if d.action.target_friend():
                            if w.elapsed_since_beginning > w.silence_until:
                                s.play(S_KEY)
                            d.mode = M_CHOOSE_FRIENDLY_TARGET
                            w.asked_for_target = w.now
                        elif d.action.target_enemy():
                            if len(e.mobs)==0:
                                d.mode = M_NORMAL
                                if w.elapsed_since_beginning > w.silence_until:
                                    s.play(S_CANCEL)
                                d.print_message('No enemies here!',None,COL_LIGHT)
                            else:
                                if w.elapsed_since_beginning > w.silence_until:
                                    s.play(S_KEY)
                                d.mode = M_CHOOSE_ENEMY_TARGET
                                w.asked_for_target = w.now
                        else:
                            if w.elapsed_since_beginning > w.silence_until:
                                s.play(S_KEY)
                            d.mode = M_NORMAL
                            d.log(d.actor.name + ' chooses ' + d.action.name())
                            d.action.trigger(None)
                    else:
                        if w.elapsed_since_beginning > w.silence_until:
                            s.play(S_CANCEL)
                        d.actor = None
                        d.action = None
                        d.mode = M_NORMAL                        
            if not found_action:
                d.mode = M_NORMAL
                if w.elapsed_since_beginning > w.silence_until:
                    s.play(S_CANCEL)
                d.print_message('Action cancelled',None,COL_LIGHT)
        elif d.mode==M_CHOOSE_FRIENDLY_TARGET and d.button_still_down==False:
            # choose a target from the options provided
            found_target = False
            for c in p.chars:
                if c.alive and (not c.about_to_die or d.action.action_code==CA_CURE_MORTAL_WOUNDS):
                    if d.pos_to_image_rect[c.pos].collidepoint(a) and d.action.friend_target_ok(c):
                        found_target = True
                        d.target = c
                        if w.elapsed_since_beginning > w.silence_until:
                            s.play(S_KEY)
                        d.mode = M_NORMAL
                        d.log(d.actor.name + ' chooses ' + d.action.name())
                        d.action.trigger(d.target)
            if not found_target:
                d.mode = M_NORMAL
                if w.elapsed_since_beginning > w.silence_until:
                    s.play(S_CANCEL)
                d.print_message('Action cancelled',None,COL_LIGHT)                    
        elif d.mode==M_CHOOSE_ENEMY_TARGET and d.button_still_down==False:
            # choose a target from the options provided
            if e.n_surviving_mobs()==0:
                d.mode = M_NORMAL
                if w.elapsed_since_beginning > w.silence_until:
                    s.play(S_CANCEL)
                d.print_message('No enemies here!',None,COL_LIGHT)
            else:
                found_target = False
                for m in e.mobs:
                    if m.alive and not m.about_to_die and d.pos_to_image_rect[m.pos].collidepoint(a) and d.action.enemy_target_ok(m):
                        found_target = True
                        d.target = m
                        if w.elapsed_since_beginning > w.silence_until:
                            s.play(S_KEY)
                        d.mode = M_NORMAL
                        d.log(d.actor.name + ' chooses ' + d.action.name())
                        d.action.trigger(d.target)
                if not found_target:
                    d.mode = M_NORMAL
                    if w.elapsed_since_beginning > w.silence_until:
                        s.play(S_CANCEL)
                    d.print_message('Action cancelled',None,COL_LIGHT)
            
if __name__ == '__main__': main()
# or:
#import cProfile as profile
#profile.run('main()','C:\\Program Files\\Python27\\PGS4A\\demo supplementary\\test\\profile.txt')

